package org.linlinjava.litemall.wx.service;

import org.linlinjava.litemall.core.config.Setting;
import org.linlinjava.litemall.core.exception.BadRequestException;
import org.linlinjava.litemall.core.system.SystemConfig;
import org.linlinjava.litemall.core.util.ResponseUtil;
import org.linlinjava.litemall.db.dao.LitemallUserMemberMapper;
import org.linlinjava.litemall.db.domain.*;
import org.linlinjava.litemall.db.service.*;
import org.linlinjava.litemall.db.util.GrouponConstant;
import org.linlinjava.litemall.db.util.SpellConstant;
import org.linlinjava.litemall.wx.dto.AnalysisOrderResult;
import org.linlinjava.litemall.wx.dto.BonusInfo;
import org.linlinjava.litemall.wx.dto.OrderRequest;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.ArrayList;
import java.util.List;

@Service
public class OrderAnalysis {
    @Autowired
    private LitemallCartService cartService;
    @Autowired
    private LitemallGrouponRulesService grouponRulesService;
    @Autowired
    private LitemallGrouponService grouponService;
    @Autowired
    private LitemallSpellService spellService;
    @Autowired
    private CouponVerifyService couponVerifyService;
    @Autowired
    private LitemallGoodsService goodsService;
    @Autowired
    private LitemallGoodsProductService goodsProductService;
    @Autowired
    private LitemallUserMemberService userMemberService;
    @Autowired
    private LitemallMemberRuleService memberRuleService;
    @Autowired
    private Setting setting;

    /**
     * 分析订单价格，与一些活动模块的基本信息
     *
     * @param userId
     * @param request
     * @param recommandCoupon
     * @return
     */
    public AnalysisOrderResult analysis(Integer userId, OrderRequest request, Boolean recommandCoupon) {
        if (recommandCoupon == null) {
            recommandCoupon = false;
        }
        AnalysisOrderResult result = new AnalysisOrderResult();
        /* 货品价格 */
        List<LitemallCart> checkedGoodsList = null;
        Integer cartId = request.getCartId();
        if (cartId == null || cartId.equals(0)) {
            checkedGoodsList = cartService.queryByUidAndChecked(userId);
        } else {
            LitemallCart cart = cartService.findById(cartId);
            checkedGoodsList = new ArrayList<>(1);
            checkedGoodsList.add(cart);
        }
        if (checkedGoodsList.size() == 0) {
            throw new BadRequestException("请选择所要下单的商品");
        }
        BigDecimal checkedGoodsPrice = new BigDecimal(0);
        BigDecimal memberPrice = new BigDecimal(0);
        for (LitemallCart checkGoods : checkedGoodsList) {
            memberPrice = memberPrice.add(checkGoods.getMemberPrice().multiply(new BigDecimal(checkGoods.getNumber()))).setScale(2, RoundingMode.UP);
            LitemallUserMember userMember = userMemberService.findByUid(userId);
            if (userMember != null) {
                checkedGoodsPrice = memberPrice;
            } else {
                checkedGoodsPrice = checkedGoodsPrice.add(checkGoods.getPrice().multiply(new BigDecimal(checkGoods.getNumber())));
            }
        }
        if (result.getDiscount() != null) {
            checkedGoodsPrice = checkedGoodsPrice.multiply(result.getDiscount()).multiply(new BigDecimal("0.1")).setScale(2, RoundingMode.UP);
        }
        result.setCheckedGoodsList(checkedGoodsList);
        result.setCheckedGoodsPrice(checkedGoodsPrice);
        result.setActualPrice(checkedGoodsPrice);
        result.setMemberPrice(memberPrice);
        result.setOrderTotalPrice(checkedGoodsPrice);

        /** 计算卡卷减价 **/
        if (setting.getCoupon()) {
            involveCoupon(result, userId, request.getCouponId(), request.getUserCouponId(), recommandCoupon);
        }
        /** 计算运费 **/
        involveFreight(result);
        return result;
    }

    /**
     * 参与拼单
     *
     * @param result
     * @param spellId
     */
    private void involveSpell(AnalysisOrderResult result, Integer userId, Integer spellId) {
        BigDecimal spellPrice = new BigDecimal(0.00);
        //拼单优惠(但商品计算拼单优惠)
        List<LitemallCart> checkedGoodsList = result.getCheckedGoodsList();
        if (checkedGoodsList.size() == 1) {
            LitemallGoods goods = goodsService.findById(checkedGoodsList.get(0).getGoodsId());
            if (goods.getSpellReduce() != null) {
                spellPrice = goods.getSpellReduce().multiply(new BigDecimal(checkedGoodsList.get(0).getNumber()));
            }
        }
        result.setSpellPrice(spellPrice);
        // 参与拼单
        LitemallSpell spellItem = null;
        if (spellId != null && !spellId.equals(0)) {
            spellItem = spellService.findById(spellId);
            if (SpellConstant.STATUS_WAIT_IN.equals(spellItem.getStatus()) && !userId.equals(spellItem.getCreatorUserId()) && checkedGoodsList.size() == 1 && checkedGoodsList.get(0).getGoodsId().equals(spellItem.getGoodsId())) {
                result.setSpell(spellItem);
                result.subtract(spellPrice);
                result.setInvolveSpell(true);
            } else {
                throw new BadRequestException("当前拼单已结束");
            }
        } else {
            result.setInvolveSpell(false);
        }

    }

    /**
     * 参与团购处理
     *
     * @param grouponRulesId
     * @param grouponLinkId
     * @return
     */
    private void involveGroupon(AnalysisOrderResult result, Integer userId, Integer grouponRulesId, Integer grouponLinkId) {
        //如果是团购项目,验证活动是否有效
        if (grouponRulesId != null && grouponRulesId > 0) {
            LitemallGrouponRules rules = grouponRulesService.findById(grouponRulesId);
            //找不到记录
            if (rules == null) {
                throw new BadRequestException("出现错误");
            }
            //团购规则已经过期
            if (rules.getStatus().equals(GrouponConstant.RULE_STATUS_DOWN_EXPIRE)) {
                throw new BadRequestException("团购已过期!");
            }
            //团购规则已经下线
            if (rules.getStatus().equals(GrouponConstant.RULE_STATUS_DOWN_ADMIN)) {
                throw new BadRequestException("团购已下线!");
            }

            if (grouponLinkId != null && grouponLinkId > 0) {
                //团购人数已满
                if (grouponService.countGroupon(grouponLinkId) >= (rules.getDiscountMember() - 1)) {
                    throw new BadRequestException("团购活动人数已满!");
                }
                // NOTE
                // 这里业务方面允许用户多次开团，以及多次参团，
                // 但是会限制以下两点：
                // （1）不允许参加已经加入的团购
                if (grouponService.hasJoin(userId, grouponLinkId)) {
                    throw new BadRequestException("团购活动已经参加!");
                }
                // （2）不允许参加自己开团的团购
                LitemallGroupon groupon = grouponService.queryById(userId, grouponLinkId);
                if (groupon != null && groupon.getCreatorUserId().equals(userId)) {
                    throw new BadRequestException("团购活动已经参加!");
                }
            }
        }

        BigDecimal grouponPrice = new BigDecimal(0.00);
        LitemallGrouponRules grouponRules = grouponRulesService.findById(grouponRulesId);
        if (grouponRules != null) {
            grouponPrice = grouponRules.getDiscount();
        }
        result.setGrouponPrice(grouponPrice);
        result.setGrouponRules(grouponRules);
    }

    /**
     * 参与折扣
     *
     * @param result
     * @param userId
     */
    private void involveDiscount(AnalysisOrderResult result, Integer userId) {
        LitemallUserMember userMember = userMemberService.findByUid(userId);
        if (userMember != null) {
            Integer memberRuleId = userMember.getMemberRuleId();
            LitemallMemberRule memberRule = memberRuleService.findById(memberRuleId);
            BigDecimal discount = memberRule.getDiscount();
            result.setDiscount(discount);

            if (discount != null) {
                result.multiply(discount);
            }
        }
    }

    /**
     * 参与卡卷
     *
     * @param result
     * @param userId
     * @param couponId
     * @param userCouponId
     */
    private void involveCoupon(AnalysisOrderResult result, Integer userId, Integer couponId, Integer userCouponId, Boolean recommandCoupon) {
        BigDecimal couponPrice = new BigDecimal(0);
        if (setting.getCoupon()) {
            RecommandCoupon recommandCouponVo = new RecommandCoupon();
            if (recommandCoupon) {
                recommandCouponVo = couponVerifyService.recommandCoupon(userId, result.getActualPrice(), result.getCheckedGoodsList());
            }
            // 这里存在三种情况
            // 1. 用户不想使用优惠券，则不处理
            // 2. 用户想自动使用优惠券，则选择合适优惠券
            // 3. 用户已选择优惠券，则测试优惠券是否合适
            if (couponId == null || couponId.equals(0)) {
                couponId = recommandCouponVo.getCouponId();
                userCouponId = recommandCouponVo.getUserCouponId();
                couponPrice = recommandCouponVo.getCouponPrice();
            } else if (couponId.equals(-1)) {
                couponId = -1;
                userCouponId = -1;
            } else {
                LitemallCoupon coupon = couponVerifyService.checkCoupon(userId, couponId, userCouponId, result.getActualPrice(), result.getCheckedGoodsList());
                // 用户选择的优惠券有问题，则选择合适优惠券，否则使用用户选择的优惠券
                if (coupon == null) {
                    if (!recommandCoupon) {
                        throw new BadRequestException("计算金额失败");
                    }
                    couponId = recommandCouponVo.getCouponId();
                    userCouponId = recommandCouponVo.getUserCouponId();
                    couponPrice = recommandCouponVo.getCouponPrice();
                } else {
                    couponPrice = coupon.getDiscount();
                }
            }
            result.setCouponPrice(couponPrice);
            result.setCouponLength(recommandCouponVo.getCouponLength());
            result.setCouponId(couponId);
            result.setUserCouponId(userCouponId);
            result.subtract(couponPrice);
        }
    }

    /**
     * 计算运费
     *
     * @param result
     */
    private void involveFreight(AnalysisOrderResult result) {
        BigDecimal freightPrice = new BigDecimal(0);
        if (result.getActualPrice().compareTo(SystemConfig.getFreightLimit()) < 0) {
            freightPrice = SystemConfig.getFreight();
        }
        result.setFreightPrice(freightPrice);
        result.add(freightPrice);
    }
}
